package tcp_server_demo

import (
	"fmt"
	"google.golang.org/grpc"
	"google.golang.org/grpc/resolver"
)

type Client struct {
	insecure         bool
	resolverBuilders []resolver.Builder
	balancerName     string
	interceptor      []grpc.UnaryClientInterceptor
}

func (c *Client) Dial(addr string) (*grpc.ClientConn, error) {
	opts := make([]grpc.DialOption, 0, 2)
	if c.insecure {
		opts = append(opts, grpc.WithInsecure())
	}
	if c.resolverBuilders != nil {
		opts = append(opts, grpc.WithResolvers(c.resolverBuilders...))
	}
	if c.balancerName != "" {
		opts = append(opts, grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"loadBalancingPolicy":"%s"}`, c.balancerName)))
	}
	if c.interceptor != nil {
		opts = append(opts, grpc.WithChainUnaryInterceptor(c.interceptor...))
	}
	return grpc.Dial(addr, opts...)
}

type Opt func(*Client)

func WithInsecure() Opt {
	return func(c *Client) {
		c.insecure = true
	}
}

func WithResolverBuilders(builders ...resolver.Builder) Opt {
	return func(c *Client) {
		c.resolverBuilders = builders
	}
}

func WithBalancerName(balancerName string) Opt {
	return func(c *Client) {
		c.balancerName = balancerName
	}
}

func WithInterceptor(interceptor ...grpc.UnaryClientInterceptor) Opt {
	return func(c *Client) {
		c.interceptor = interceptor
	}
}

func NewClient(opts ...Opt) *Client {
	c := &Client{}

	for _, opt := range opts {
		opt(c)
	}

	return c
}
